﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MX.Core.Caching
{
    /// <summary>
    /// 缓存驱动
    /// </summary>
    public interface ICaching : IDisposable
    {
        /// <summary>
        /// 获取某个项
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns></returns>
        object Get(string key);
        
        /// <summary>
        /// 获取某个项
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns></returns>
        T Get<T>(string key);

        /// <summary>
        /// 尝试获取某项数据
        /// </summary>
        /// <typeparam name="T">值类型</typeparam>
        /// <param name="key">键值</param>
        /// <param name="value">返回的值，如果不存在则返回默认值</param>
        /// <returns>是否获取成功</returns>
        bool TryGet<T>(string key, out T value);

        /// <summary>
        /// 获取一批数据
        /// </summary>
        /// <param name="keys">键值</param>
        /// <returns></returns>
        IDictionary<string, object> GetAll(string[] keys);
        /// <summary>
        /// 获取一批数据
        /// </summary>
        /// <param name="keys">键值</param>
        /// <returns></returns>
        IDictionary<string, T> GetAll<T>(string[] keys);

        /// <summary>
        /// 删除某个数据
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns></returns>
        bool Remove(string key);

        /// <summary>
        /// 删除一批数据
        /// </summary>
        /// <param name="keys">键值</param>
        /// <returns></returns>
        void RemoveAll(IEnumerable<string> keys);

        /// <summary>
        /// 判断是否存在某个键值的缓存数据
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns></returns>
        bool Exists(string key);

        /// <summary>
        /// 设置一个缓存项
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <returns></returns>
        void Set(string key, object data);
        /// <summary>
        /// 设置一个明确类型的缓存项
        /// </summary>
        /// <typeparam name="T">缓存数据的类型</typeparam>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        void Set<T>(string key, T data);

        /// <summary>
        /// 设置一个缓存项并且设置绝对过期时间
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="absoluteExpiration">绝对的过期时间,到此时间后缓存项自动过期</param>
        /// <returns></returns>
        void Set(string key, object data, DateTimeOffset absoluteExpiration);
        /// <summary>
        /// 设置一个明确类型的缓存项并且设置绝对过期时间
        /// </summary>
        /// <typeparam name="T">缓存数据的类型</typeparam>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="absoluteExpiration">绝对的过期时间,到此时间后缓存项自动过期</param>
        void Set<T>(string key, T data, DateTimeOffset absoluteExpiration);

        /// <summary>
        /// 设置一个与某些文件关连的缓存项,当这些文件被修改时缓存过期
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="dependentFiles">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <returns></returns>
        void Set(string key, object data, params string[] dependentFiles);
        /// <summary>
        /// 设置一个明确类型的且与某些文件关连的缓存项,当这些文件被修改时缓存过期
        /// </summary>
        /// <typeparam name="T">缓存数据的类型</typeparam>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="dependentFiles">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <returns></returns>
        void Set<T>(string key, T data, params string[] dependentFiles);

        /// <summary>
        /// 设置一个具有过期时间并且与某些文件关连的缓存项,当过期时间已到或这些文件被修改时缓存过期
        /// </summary>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="absoluteExpiration">绝对的过期时间,到此时间后缓存项自动过期</param>
        /// <param name="dependentFiles">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <returns></returns>
        void Set(string key, object data, DateTimeOffset absoluteExpiration, params string[] dependentFiles); 
        
        /// <summary>
        /// 设置一个明确类型的且具有过期时间并且与某些文件关连的缓存项,当过期时间已到或这些文件被修改时缓存过期
        /// </summary>
        /// <typeparam name="T">缓存数据的类型</typeparam>
        /// <param name="key">键值</param>
        /// <param name="data">缓存数据</param>
        /// <param name="absoluteExpiration">绝对的过期时间,到此时间后缓存项自动过期</param>
        /// <param name="dependentFiles">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <returns></returns>
        void Set<T>(string key, T data, DateTimeOffset absoluteExpiration, params string[] dependentFiles);

        /// <summary>
        /// 返回某个缓存项,如果不存在则调用函数委托获取值,并将值存入缓存后返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="handler">缓存项不存在时重新获取数据的函数委托</param>
        /// <returns></returns>
        T GetOrAdd<T>(string key, Func<T> handler);

        /// <summary>
        /// 返回某个缓存项,如果不存在则调用函数委托获取值,并将值存入缓存后返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="absoluteExpiration">绝对的过期时间，当时间超过此值时缓存项将自动失效</param>
        /// <param name="handler">缓存项不存在时重新获取数据的函数委托</param>
        /// <returns></returns>
        T GetOrAdd<T>(string key, Func<T> handler, DateTimeOffset absoluteExpiration);

        /// <summary>
        /// 返回某个缓存项,如果不存在则调用函数委托获取值,并将值存入缓存后返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="files">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <param name="handler">缓存项不存在时重新获取数据的函数委托</param>
        /// <returns></returns>
        T GetOrAdd<T>(string key, Func<T> handler, params string[] files);

        /// <summary>
        /// 返回某个缓存项,如果不存在则调用函数委托获取值,并将值存入缓存后返回
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存项键值</param>
        /// <param name="absoluteExpiration">绝对的过期时间，当时间超过此值时缓存项将自动失效</param>
        /// <param name="files">缓存依赖的文件地址，当这些文件有变更时缓存项将自动失效</param>
        /// <param name="handler">缓存项不存在时重新获取数据的函数委托</param>
        /// <returns></returns>
        T GetOrAdd<T>(string key, Func<T> handler, DateTimeOffset absoluteExpiration, params string[] files);

        /// <summary>
        /// 增加值
        /// </summary>
        /// <param name="key">缓存项键值</param>
        /// <param name="amount">需要增加的值</param>
        /// <returns></returns>
        long Increment(string key, uint amount);

        /// <summary>
        /// 减去值
        /// </summary>
        /// <param name="key">缓存项键值</param>
        /// <param name="amount">需要减去的值</param>
        /// <returns></returns>
        long Decrement(string key, uint amount);
    }
}
